package com.merryituxz.o2o.util.wechat;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.merryituxz.o2o.dto.UserAccessToken;
import com.merryituxz.o2o.dto.WechatUser;
import com.merryituxz.o2o.entity.PersonInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;

public class WechatUtil {
    private static Logger logger = LoggerFactory.getLogger(WechatUtil.class);

    /**
     * 将WechatUser里的信息转换成PersonInfo的信息, 返回PersonInfo实体类
     *
     * @param wechatUser
     * @return
     */
    public static PersonInfo getPersonInfoFromRequest(WechatUser wechatUser) {
        PersonInfo personInfo = new PersonInfo();
        personInfo.setName(wechatUser.getNickName());
        personInfo.setGender(wechatUser.getSex() + "");
        personInfo.setProfileImg(wechatUser.getHeadimgurl());
        personInfo.setEnableStatus(1);
        return personInfo;
    }

    /**
     * 根据code获取UserAccessToken实体类
     *
     * @param code
     * @return
     */
    public static UserAccessToken getUserAccessToken(String code) {
        String appId = "wx12a532cf8febe4e2";
        logger.debug("appId: " + appId);
        String appsecret = "431b84023acd95f735784ffbaf7d2ca5";
        logger.debug("secret: " + appsecret);
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
                + appId + "&secret=" + appsecret + "&code=" + code + "&grant_type=authorization_code";
        String tokenStr = httpsRequest(url, "GET", null);
        logger.debug("userAccessToken: " + tokenStr);
        UserAccessToken token = new UserAccessToken();
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            token = objectMapper.readValue(tokenStr, UserAccessToken.class);
        } catch (JsonParseException e) {
            logger.error("获取用户accessToken失败: " + e.getMessage());
            e.printStackTrace();
        } catch (JsonMappingException e) {
            logger.error("获取用户accessToken失败: " + e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            logger.error("获取用户accessToken失败: " + e.getMessage());
            e.printStackTrace();
        }
        if (token == null) {
            logger.error("获取用户accessToken失败.");
            return null;
        }
        return token;
    }

    /**
     * 获取WechatUset实体类
     *
     * @param accessToken
     * @param openId
     * @return
     */
    public static WechatUser getUserInfo(String accessToken, String openId) {
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token="
                + accessToken + "&openid=" + openId + "&lang=zh_CN";
        String userStr = httpsRequest(url, "GET", null);
        logger.debug("user info: " + userStr);
        WechatUser user = new WechatUser();
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            user = objectMapper.readValue(userStr, WechatUser.class);
        } catch (JsonMappingException e) {
            logger.error("获取用户信息失败: " + e.getMessage());
            e.printStackTrace();
        } catch (JsonProcessingException e) {
            logger.error("获取用户信息失败: " + e.getMessage());
            e.printStackTrace();
        }
        if (user == null) {
            logger.error("获取用户信息配置失败.");
            return null;
        }
        return user;
    }

    /**
     * 发起https请求并获取结果
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式(GET POST)
     * @param outputStr     提交的数据
     * @return JSON字符串
     */
    private static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        StringBuffer stringBuffer = new StringBuffer();
        try {
            TrustManager[] trustManagers = new TrustManager[]{new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, trustManagers, new SecureRandom());
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
            httpsURLConnection.setSSLSocketFactory(sslSocketFactory);

            httpsURLConnection.setDoOutput(true);
            httpsURLConnection.setDoInput(true);
            httpsURLConnection.setUseCaches(false);
            // 设置请求方式(GET / POST)
            httpsURLConnection.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod)) {
                httpsURLConnection.connect();
            }

            if (outputStr != null) {
                OutputStream outputStream = httpsURLConnection.getOutputStream();
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            InputStream inputStream = httpsURLConnection.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                stringBuffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            httpsURLConnection.disconnect();
            logger.debug("https buffer: " + stringBuffer.toString());
        } catch (ConnectException e) {
            logger.error("Wechat server connection timed out.");
        } catch (Exception e) {
            logger.error("https request error: {}", e);
        }
        return stringBuffer.toString();
    }
}
